
#include <iostream>
#include <dlfcn.h>
#include "consDriver.h"
#include "Debug.h"

#define LIB_DIR  "lib"

ConsumerDriver::ConsumerDriver() {
  consName = "";
  consLibrary = "";
  fFunc = NULL;
  libHandle = NULL;
  libError = "";
  status = false;
}

ConsumerDriver::ConsumerDriver(const char *consumer, const string& consumer_lib_name, int flags) 
{
  consName = consumer;
  fFunc = NULL;
  libHandle = NULL;
  libError = "";
  status = false;
  consLibrary = consumer_lib_name;
  loadLibrary(flags);
}

ConsumerDriver::~ConsumerDriver() {
  unloadLibrary();
}

void*
ConsumerDriver::getFunc(const char *suffix)
{
	if (libHandle == NULL) {
		libError = "Oops! No library was loaded previously\n";
		cerr << libError <<endl;
		return NULL;
	}

	string funcName = consName + suffix;
	void* func = dlsym(libHandle, funcName.c_str());
	if (func == NULL) {
		if (!((libError = dlerror()).empty())) {
			cerr << "Error calling " << funcName <<endl;
			cerr << "  " << libError <<endl;
			return NULL;
		}
	}
	return func;
}

bool ConsumerDriver::callInit(const char *consumer, const char* conf)
{
	InitFunc func;
	if ((func = (InitFunc)getFunc(LOG_CONS_INIT_SUFFIX)) != NULL) {
		return (*func)(consumer, conf);
	} else {
		return false;
	}
}

void ConsumerDriver::callShutdown()
{
  ShutdownFunc func;
  if ((func = (ShutdownFunc)getFunc(LOG_CONS_SHUTDOWN_SUFFIX)) != NULL) {
    (*func)();
  }
}

void ConsumerDriver::callFlush(const char *consumer)
{
  FlushFunc func;
  if ((func = (FlushFunc)getFunc(LOG_CONS_FLUSH_SUFFIX)) != NULL) {
    (*func)(consumer);
  }
}


bool ConsumerDriver::callFriends(const char *user, GHashTable *frs)
{

	if (fFunc != NULL || 
			(fFunc = (FriendsFunc)getFunc(LOG_CONS_FRIENDS_SUFFIX)) != NULL) {
		return (*fFunc)(user, frs); 
	} else {
		return false;
	}
}

bool ConsumerDriver::loadLibrary(int flags) {
	// First unload any library we loaded previously
	unloadLibrary();

	status = true;  // assume we'll succeed
	libHandle = dlopen(consLibrary.c_str(), flags);
	if (libHandle == NULL) {
		libError = dlerror();
		cerr << "Couldn't load library " << consLibrary <<endl;
		cerr << libError <<endl;
		status = false;
	} else {
		cerr << "Loaded library " << consLibrary.c_str() <<endl;
	}
	return status;
}

void ConsumerDriver::unloadLibrary() {
	if (libHandle != NULL) {
		dlclose(libHandle);
		libHandle = NULL;
	}
}
